package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.admin.domain.entity.AppInstallEntity;
import com.xbongbong.admin.model.AppInstallModel;
import com.xbongbong.admin.pojo.dto.MirrorRollBackDTO;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.PaasProcessTemplateEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasMenuEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateNodeEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.MenuTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.model.AttrTrashModel;
import com.xbongbong.paas.model.FineClueCompanyModel;
import com.xbongbong.paas.model.FineClueUserModel;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.model.PaasProcessDataModel;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.model.PaasProcessTemplateNodeModel;
import com.xbongbong.paas.model.SearchCustomerCompanyModel;
import com.xbongbong.paas.pojo.ApplicationSortPoJo;
import com.xbongbong.paas.pojo.dto.ApplicationAddDTO;
import com.xbongbong.paas.pojo.dto.ApplicationCopyDTO;
import com.xbongbong.paas.pojo.dto.ApplicationDelDTO;
import com.xbongbong.paas.pojo.dto.ApplicationListDTO;
import com.xbongbong.paas.pojo.dto.ApplicationSortDTO;
import com.xbongbong.paas.pojo.dto.ApplicationUpdateDTO;
import com.xbongbong.paas.pojo.dto.CheckAllowRollBackDTO;
import com.xbongbong.paas.pojo.dto.EnableApplicationListDTO;
import com.xbongbong.paas.pojo.vo.ApplicationAddVO;
import com.xbongbong.paas.pojo.vo.ApplicationCopyVO;
import com.xbongbong.paas.pojo.vo.ApplicationDelVO;
import com.xbongbong.paas.pojo.vo.ApplicationListVO;
import com.xbongbong.paas.pojo.vo.ApplicationSortVO;
import com.xbongbong.paas.pojo.vo.ApplicationUpdateVO;
import com.xbongbong.paas.pojo.vo.CheckAllowRollBackVo;
import com.xbongbong.paas.pojo.vo.EnableApplicationListVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisConstant;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.redis.RedisTimeConstant;
import com.xbongbong.paas.service.FeeLogService;
import com.xbongbong.paas.service.MirrorService;
import com.xbongbong.paas.service.PaasAppService;
import com.xbongbong.paas.service.PackageService;
import com.xbongbong.paas.service.ProAppService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.app.pojo.dto.AppEnableDTO;
import com.xbongbong.pro.app.pojo.dto.ApplicationAddBatchDTO;
import com.xbongbong.pro.app.pojo.dto.HasFormDataDTO;
import com.xbongbong.pro.app.pojo.vo.AppEnableVO;
import com.xbongbong.pro.app.pojo.vo.ApplicationAddBatchVO;
import com.xbongbong.pro.app.pojo.vo.ApplicationVO;
import com.xbongbong.pro.app.pojo.vo.HasFormDataVO;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.constant.PackageConstant;
import com.xbongbong.pro.domain.entity.FineClueCompanyEntity;
import com.xbongbong.pro.domain.entity.SearchCustomerCompanyEntity;
import com.xbongbong.pro.enums.ContractCompareFeeStatusEnum;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.FineClueEnum;
import com.xbongbong.pro.enums.ModuleAppLabelTypeEnum;
import com.xbongbong.pro.enums.PackageStatusEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.SoukeMealEnum;
import com.xbongbong.pro.enums.ValueAddedTypeEnum;
import com.xbongbong.pro.enums.errorcodes.ProErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.menu.enums.FineClueComboEnum;
import com.xbongbong.pro.enums.menu.enums.SystemAppMenuEnum;
import com.xbongbong.pro.enums.packages.enums.FeaturesEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.packageInfo.pojo.vo.BasePackageInfoVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.MirrorRollBackTypeEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.PaasFormDataModel;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.service.toolbox.help.PackageStatusHelp;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.domain.entity.FeeLogEntity;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.FeeLogModel;
import com.xbongbong.util.ContractCompareUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 *
 * @author wufeng
 * @date 2018/8/24 14:23
 * @param
 * @descption
 * @return
 */
@Service("paasAppService")
public class PaasAppServiceImpl implements PaasAppService {

    private static final Logger LOG = LoggerFactory.getLogger(PaasAppServiceImpl.class);

    /**
     * 应用名称的长度
     */
    private static final Integer NAME_LENGTH = 20;

    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private PaasMenuModel paasMenuModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private PaasProcessTemplateNodeModel paasProcessTemplateNodeModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private LogHelp logHelp;
    @Resource
    private PackageStatusHelp packageStatusHelp;
    @Resource
    private SearchCustomerCompanyModel searchCustomerCompanyModel;
    @Resource
    private AppInstallModel appInstallModel;
    @Resource
    private MirrorService mirrorService;
    @Resource
    private PackageService packageService;
    @Resource
    private PackageHelp packageHelp;
    @Resource
    private PaasFormDataModel paasFormDataModel;
    @Resource
    private PaasProcessDataModel paasProcessDataModel;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private AttrTrashModel attrTrashModel;
    @Resource
    private FeeLogModel feeLogModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private FineClueUserModel fineClueUserModel;
    @Resource
    private FineClueCompanyModel fineClueCompanyModel;
    @Resource
    private ContractCompareUtil contractCompareUtil;
    @Resource
    private ProAppService proAppService;
    @Resource
    private FeeLogService feeLogService;

    @Override
    public ApplicationAddVO addPaasApp(ApplicationAddDTO applicationAddDTO) throws XbbException {
        LOG.info("========================addPaasApp========================");
        PaasAppEntity paasAppEntity = new PaasAppEntity();
        BeanUtils.copyProperties(applicationAddDTO, paasAppEntity);
        paasAppEntity.setCreatorId(Objects.toString(applicationAddDTO.getUserId(), ""));
        try {
            String corpid = applicationAddDTO.getCorpid();
            //套餐判断
            Integer status = packageStatusHelp.getPackageStatus(corpid, ValueAddedTypeEnum.CUSTOM_APPLICATION_NUM, 1);
            if(!Objects.equals(status, PackageStatusEnum.NORMAL.getCode()) && !Objects.equals(status, PackageStatusEnum.WARNING.getCode())){
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260013);
            }
            Map<String, Object> map = BeanUtil.convertBean2Map(applicationAddDTO, true);
            map.put("orderByStr", "sort ASC, update_time ASC ");
            List<PaasAppEntity> appList = paasAppModel.findEntitys(map);
            if(Objects.isNull(appList)){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            // 当sort为空时，自动自增
            if(paasAppEntity.getSort() == null){
                PaasAppEntity lastAppEntity  = appList.get(appList.size()-1);
                Integer count = appList.size();
                if (lastAppEntity .getSort() > count) {
                    count = lastAppEntity .getSort();
                }
                paasAppEntity.setSort(count+1);
            }
            paasAppEntity.setCreatorId(Objects.toString(applicationAddDTO.getUserId(), ""));
            paasAppModel.insert(paasAppEntity);
            //应用是市场管理的话，刷新缓存
            String marketManagementAlias = SystemAppMenuEnum.MARKET_MANAGEMENT.getAlias();
            if(Objects.equals(paasAppEntity.getAlias(),marketManagementAlias)){
                setEnable2RedisByAlias(corpid,marketManagementAlias,paasAppEntity.getEnable());
            }
            String key = corpid + "_"+ ValueAddedTypeEnum.CUSTOM_APPLICATION_NUM.getType();
            paasRedisHelper.removeValue(RedisPrefixConstant.VALUE_ADDED, key);
        } catch (XbbException e) {
            LOG.info("========================addPaasApp XbbException========================");
            throw e;
        } catch (Exception e) {
            LOG.info("========================addPaasApp paasApp数据库插入出错========================");
            LOG.error("paasApp数据库插入出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        String corpid = applicationAddDTO.getCorpid();
        String userId = Objects.toString(applicationAddDTO.getUserId(), "");
        String userName = Objects.toString(applicationAddDTO.getLoginUserName(), "");
        // 记录日志
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_APP), userName, paasAppEntity.getName());
        mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PAAS_APP, OperateTypeEnum.NEW,
                paasAppEntity.getId().toString(), paasAppEntity.getName(), memo, applicationAddDTO.getHttpHeader());


        ApplicationAddVO applicationAddVO = new ApplicationAddVO();
        applicationAddVO.setAppId(paasAppEntity.getId());
        LOG.info("========================addPaasApp applicationAddVO========================" + applicationAddVO.getAppId());
        return applicationAddVO;
    }

    @Override
    public ApplicationAddBatchVO addBatchPaasApp(ApplicationAddBatchDTO applicationAddBatchDTO) throws XbbException {
       return proAppService.addBatchPaasApp(applicationAddBatchDTO);
    }

    @Override
    public ApplicationListVO listPaasApp(ApplicationListDTO applicationListDTO) throws XbbException {
        ApplicationListVO applicationListVO = new ApplicationListVO();
        try {
            Map<String, Object> map = BeanUtil.convertBean2Map(applicationListDTO, true);
            map.put("orderByStr", "sort ASC, update_time ASC ");
            List<PaasAppEntity> list = paasAppModel.list(map);
            if(list == null){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.APP_NOT_EXIST);
            }
            List<ApplicationVO> appList = new ArrayList<>();
            List<ApplicationVO> unEnableAppList = new ArrayList<>();

            SearchCustomerCompanyEntity soukeEntity = searchCustomerCompanyModel.getByCorpid(applicationListDTO.getCorpid(), SoukeMealEnum.SOUKE.getType());

            //查询通过镜像安装的应用
            map.clear();
            map.put("corpid",applicationListDTO.getCorpid());
            map.put("del",DelEnum.NORMAL.getDel());
            map.put("installType",BasicConstant.ONE);
            map.put("noMirrorApplicationType",BasicConstant.THREE);
            List<AppInstallEntity> entitys = appInstallModel.findEntitys(map);
            HashSet<Long> mirrorIds = new HashSet<>();
            HashMap<Long,Long> appIdToInstallId = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            entitys.forEach(item->{
                if (isAllowShowRollBack(item)){
                    mirrorIds.add(item.getAppId());
                    appIdToInstallId.put(item.getAppId(),item.getId());
                }
            });
            UserVO loginUser = applicationListDTO.getLoginUser();
            boolean adminOrBoss = loginUser.isAdminOrBoss();
            boolean admin = loginUser.isAdmin();
            boolean havePermission =true;
            if (!loginUser.getPermSet().contains(ProPermissionAliasEnum.APPLICATION_UPDATE.getAlias())){
                havePermission=false;
            }
            List<String> featureList = packageHelp.getFeatureList(applicationListDTO.getCorpid());
            Boolean pastDue = feeLogService.workOrderV2PastDue(applicationListDTO.getCorpid());
            for (PaasAppEntity item : list) {
                if (Objects.equals(item.getAlias(), XbbRefTypeEnum.SEARCH_CUSTOMER.getAlias())){
                    //判断精线索是否可用
                    FineClueCompanyEntity fineClueCompanyEntity = fineClueCompanyModel.getByCorpid(loginUser.getCorpid(), FineClueEnum.FINE_CLUE.getType());
                    // 精线索存在，旧搜客应用不显示
                    if (Objects.nonNull(fineClueCompanyEntity)) {
                        if (fineClueCompanyEntity.getExtraExpiry() > DateUtil.getInt()) {
                            ApplicationVO applicationVO = new ApplicationVO();
                            BeanUtil.copyProperties(item, applicationVO);
                            applicationVO.setAlias("fineCluePermission");
                            if(item.getEnable().equals(1)){
                                appList.add(applicationVO);
                            }else{
                                unEnableAppList.add(applicationVO);
                            }
                        }
                        continue;
                    }
                    // 搜客过期不给展示,试用搜客不给展示
                    if (soukeEntity == null || soukeEntity.getExtraExpiry() <= DateUtil.getInt()) {
                        continue;
                    }
                    if (soukeEntity.getExtraExpiry() - soukeEntity.getAddTime() < 4* RedisConstant.LONG_DURATION) {
                        continue;
                    }
                }

                //每刻报销模板不展示，这边的模板入口也隐藏掉
                if (Objects.equals(item.getAlias(), XbbRefTypeEnum.EXPENSE_MANAGEMENT.getAlias())) {
                    continue;
                }


                ApplicationVO applicationVO = new ApplicationVO();
                BeanUtil.copyProperties(item, applicationVO);
                // 【旗舰->标准/高级】不能进入应用，前端和设置可显示可删除，不可进入；提示版本限制
                if (!featureList.contains(FeaturesEnum.APPLICATION.getAlias()) && Objects.equals(SaasMarkEnum.PAAS.getCode(), item.getSaasMark())) {
                    applicationVO.setPackageLimit(1);
                    applicationVO.setMessage(I18nMessageUtil.getMessage(PackageConstant.APPLICATION_PACKAGE_LIMIT_MESSAGE));
                    if (admin) {
                        applicationVO.setDelete(1);
                        applicationVO.setUpgrade(1);
                    }
                }
                if (Objects.equals(item.getAlias(), XbbRefTypeEnum.WORK_ORDER_V2_CENTER.getAlias()) && pastDue) {
                    applicationVO.setPackageLimit(1);
                    applicationVO.setMessage(I18nMessageUtil.getMessage(PackageConstant.APPLICATION_PACKAGE_LIMIT_MESSAGE));
                }
                //做是否可以回退到上一个版本的判断(镜像3.0)
                if (mirrorIds.contains(item.getId()) && (adminOrBoss || havePermission ) && Objects.equals(SaasMarkEnum.SAAS.getCode(),item.getSaasMark())){
                    applicationVO.setAllowRollBackToPrevious(1);
                    applicationVO.setInstallId(appIdToInstallId.get(item.getId()));
                }else{
                    applicationVO.setAllowRollBackToPrevious(0);
                }
                if (Objects.equals(item.getAlias(), XbbRefTypeEnum.JXC.getAlias())) {
                    applicationVO.setSaasMarkMemo(ModuleAppLabelTypeEnum.LIMITE_FREE.getName());
                } else {
                    applicationVO.setSaasMarkMemo(SaasMarkEnum.getMemo(item.getSaasMark()).getMemo());
                }
                applicationVO.setSaasMarkColor(SaasMarkEnum.getMemo(item.getSaasMark()).getColor());
                if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getAlias(), item.getAlias())) {
                    PaasMenuEntity paasMenuEntity = paasMenuModel.getByAlias(item.getAlias(), item.getId(), item.getCorpid());
                    if (Objects.nonNull(paasMenuEntity)) {
                        applicationVO.setMenuId(paasMenuEntity.getId());
                    }
                    applicationVO.setBusinessType(XbbRefTypeEnum.getByAlias(item.getAlias()).getCode());
                    applicationVO.setSubBusinessType(XbbRefTypeEnum.getByAlias(item.getAlias()).getCode());
                }
                if (Objects.equals(XbbRefTypeEnum.DISTRIBUTOR.getAlias(), item.getAlias())) {
                    applicationVO.setDistributorMark(DistributorMarkEnum.DISTRIBUTOR.getCode());
                }
                if (Objects.equals(XbbRefTypeEnum.CONTRACT_COMPARE.getAlias(), item.getAlias())){
                    Integer compareStatus = contractCompareUtil.getContractCompareStatus(applicationListDTO.getCorpid());
                    if (Objects.equals(compareStatus, ContractCompareFeeStatusEnum.TRIAL.getType())){
                        applicationVO.setCompareFeeStatus(BasicConstant.ZERO);
                    } else {
                        applicationVO.setCompareFeeStatus(BasicConstant.ONE);
                    }
                }
                if(item.getEnable().equals(1)){
                    appList.add(applicationVO);
                }else{
                    unEnableAppList.add(applicationVO);
                }
            }
            // TODO 获取公司级配置 伪装应用
            List<String> aliasList = Arrays.asList(CompanyConfigEnum.PRICE_MANAGE.getAlias(), CompanyConfigEnum.LOGISTICS_TRACKING.getAlias(), CompanyConfigEnum.ELECTRONIC_FACE_SHEET.getAlias());
            Map<String,String> companyConfigMap = companyConfigModel.getConfigValueMap(applicationListDTO.getCorpid(), aliasList);

            applicationListVO.setAppList(appList);
            applicationListVO.setUnEnableAppList(unEnableAppList);
            // 国际化白名单
            CompanyConfigEntity entity = companyConfigModel.getByConfigAlias(CompanyConfigEnum.I18N_WHITE.getAlias(), PaasConstant.DEFAULT_DATA_CORPID);
            String value = CompanyConfigEnum.I18N_WHITE.getValue();
            if (Objects.nonNull(entity)) {
                value = entity.getConfigValue();
            }
            List<String> whiteList = JsonHelperUtil.parseArray(value, String.class);
            boolean flag = CollectionsUtil.isNotEmpty(whiteList) && whiteList.contains(applicationListDTO.getCorpid());
            applicationListVO.setMultiLang(flag);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("paasApp数据库查询出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return applicationListVO;
    }

    /**
     * 判断是否可以展示回退按钮(管理中心)
     * @param item
     * @return
     */
    private boolean isAllowShowRollBack(AppInstallEntity item) {
        return Objects.equals(item.getIsBack(), BasicConstant.ONE) && (Objects.equals(item.getIsToPrevious(), MirrorRollBackTypeEnum.NO_ROLL_BACK_TO_PREVIOUS.getFlag()) || Objects.equals(item.getIsToInit(),MirrorRollBackTypeEnum.NO_ROLL_BACK_TO_INIT.getFlag()));
    }

    @Override
    public ApplicationDelVO deletePaasApp(ApplicationDelDTO applicationDelDTO) throws XbbException {
        String corpid = applicationDelDTO.getCorpid();
        PaasAppEntity paasAppEntity = new PaasAppEntity();
        BeanUtils.copyProperties(applicationDelDTO, paasAppEntity);
        try {
            PaasAppEntity entity = paasAppModel.getByKey(applicationDelDTO.getId(), corpid);
            if (entity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.APP_NOT_EXIST);
            }
            if(SaasMarkEnum.SAAS.getCode().equals(entity.getSaasMark())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.APP_NOT_ALLOW_DELETE, entity.getName());
            }
            paasAppEntity.setName(entity.getName());
            // 判断表单是否存在
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("appId", entity.getId());
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            Integer count = paasFormModel.getEntitysCount(param);
            if (count > 0) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.APP_HAS_FORM_NOT_ALLOW_DELETE, entity.getName());
            }
            // 判断菜单是否存在
            param.clear();
            param.put("appId", entity.getId());
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            count = paasMenuModel.getEntitysCount(param);
            if (count > 0) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.APP_HAS_MENU_NOT_ALLOW_DELETE, entity.getName());
            }
            paasAppModel.delete(applicationDelDTO.getId(), corpid);
            String key = corpid + "_"+ ValueAddedTypeEnum.CUSTOM_APPLICATION_NUM.getType();
            paasRedisHelper.removeValue(RedisPrefixConstant.VALUE_ADDED, key);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("paasApp数据库删除出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        String userId = applicationDelDTO.getUserId();
        String userName = applicationDelDTO.getLoginUserName();
        // 记录日志
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_APP), userName, paasAppEntity.getName());
        mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PAAS_APP, OperateTypeEnum.DELETE, paasAppEntity.getId().toString(),
                paasAppEntity.getName(), memo, applicationDelDTO.getHttpHeader());

        ApplicationDelVO applicationDelVO = new ApplicationDelVO();
        applicationDelVO.setAppId(paasAppEntity.getId());
        return applicationDelVO;
    }

    @Override
    public ApplicationUpdateVO updatePaasApp(ApplicationUpdateDTO applicationUpdateDTO) throws XbbException {
        return proAppService.updatePaasApp(applicationUpdateDTO);
    }

    @Override
    public ApplicationSortVO updateSort(ApplicationSortDTO applicationSortDTO) throws XbbException {
        String corpid = applicationSortDTO.getCorpid();
        List<PaasAppEntity> paasAppEntityList = new ArrayList<>();
        List<ApplicationSortPoJo> list = applicationSortDTO.getAppSort();

        try {
            for(ApplicationSortPoJo applicationSortPoJo : list) {
                PaasAppEntity paasAppEntity = new PaasAppEntity();
                Long id = applicationSortPoJo.getId();
                Integer sort = applicationSortPoJo.getSort();
                if (id == null || sort == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, SystemErrorCodeEnum.API_ERROR_100002.getMsg());
                }
                paasAppEntity.setId(id);
                paasAppEntity.setSort(sort);
                paasAppEntityList.add(paasAppEntity);
            }
            paasAppModel.updateSort(paasAppEntityList, corpid);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e){
            LOG.error("paasApp数据库更新出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        String userId = applicationSortDTO.getUserId();
        String userName = applicationSortDTO.getLoginUserName();
        // 记录日志
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_APP_SORT), userName, "");
        mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PAAS_APP, OperateTypeEnum.EDIT, applicationSortDTO.getCorpid(),
                "", memo, applicationSortDTO.getHttpHeader());


        ApplicationSortVO applicationSortVO = new ApplicationSortVO();
        applicationSortVO.setAppSort(list);
        return applicationSortVO;
    }

    @Override
    public EnableApplicationListVO enableAppList(EnableApplicationListDTO enableApplicationListDTO) throws XbbException {
        EnableApplicationListVO enableApplicationListVO = new EnableApplicationListVO();
        try {
            Map<String, Object> map = BeanUtil.convertBean2Map(enableApplicationListDTO, true);
            List<PaasAppEntity> list = paasAppModel.userAppList(map);
            if(list == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.APP_NOT_EXIST);
            }
//            AtomicBoolean contractCompare = new AtomicBoolean(false);
//            list.forEach(app -> {if (Objects.equals(app.getAlias(), ValueAddedTypeEnum.CONTRACT_COMPARE.getAlias())){
//                contractCompare.set(true);}});
//            // 合同对比默认为试用状态，塞个假应用
//            if (!contractCompare.get()){
//                PaasAppEntity paasAppEntity = new PaasAppEntity();
////                paasAppEntity.setId(0L);
//                paasAppEntity.setStatus(0);
//                paasAppEntity.setCorpid(enableApplicationListDTO.getCorpid());
//                paasAppEntity.setEnable(1);
//                paasAppEntity.setAlias(ValueAddedTypeEnum.CONTRACT_COMPARE.getAlias());
//                paasAppEntity.setSaasMark(SaasMarkEnum.SAAS.getCode());
//                paasAppEntity.setName(ValueAddedTypeEnum.CONTRACT_COMPARE.getName());
//                paasAppEntity.setDel(0);
//                paasAppEntity.setAddTime(DateTimeUtil.getInt());
//                paasAppEntity.setUpdateTime(DateTimeUtil.getInt());
//                list.add(paasAppEntity);
//            }
            //老搜客已过期，新搜客没有试用/开通过，把applist中的搜客app实体remove掉--->前端搜客应用展示为试用
            FineClueCompanyEntity fineClueCompany = fineClueCompanyModel.getByCorpid(enableApplicationListDTO.getCorpid(), FineClueComboEnum.FINE_CLUE.getCode());
            SearchCustomerCompanyEntity searchCustomerCompany= searchCustomerCompanyModel.getByCorpid(enableApplicationListDTO.getCorpid(), 1);
            if (Objects.isNull(fineClueCompany) && Objects.nonNull(searchCustomerCompany) && searchCustomerCompany.getExtraExpiry() < DateTimeUtil.getInt()){
                list.removeIf(l -> Objects.equals(l.getAlias(),ValueAddedTypeEnum.SEARCH_CUSTOMER.getAlias()));
            }
            // 经销商、搜客处理套餐状态
            list.forEach(i -> {
                if (Objects.equals(i.getAlias(), ValueAddedTypeEnum.DISTRIBUTOR.getAlias()) || Objects.equals(i.getAlias(), ValueAddedTypeEnum.SEARCH_CUSTOMER.getAlias()) || Objects.equals(i.getAlias(), ValueAddedTypeEnum.CONTRACT_COMPARE.getAlias())) {
                    int feeType = Objects.equals(i.getAlias(), ValueAddedTypeEnum.SEARCH_CUSTOMER.getAlias()) ? ValueAddedTypeEnum.SEARCH_CUSTOMER.getType() : ValueAddedTypeEnum.DISTRIBUTOR.getType();
                    Map<String, Object> param = new HashMap<>(4);
                    param.put("del", 0);
                    param.put("feeType", feeType);
                    param.put("corpid", i.getCorpid());
                    param.put("columns", " corpid, end_time ");
                    List<FeeLogEntity> feeLogEntityList = feeLogModel.findEntitys(param);
                    for (FeeLogEntity j : feeLogEntityList) {
                        if (j.getEndTime() < DateTimeUtil.getTodayInt()) {
                            // 过期，还需要继续循环看是否有没过期套餐
                            i.setStatus(0);
                        } else {
                            // 只要有一个套餐没过期，就是没过期
                            i.setStatus(1);
                            break;
                        }
                    }
                    //新搜客试用情况
                    if (Objects.equals(i.getAlias(), ValueAddedTypeEnum.SEARCH_CUSTOMER.getAlias())) {
                        FineClueCompanyEntity fineClueCompanyEntity = fineClueCompanyModel.getByCorpid(enableApplicationListDTO.getCorpid(), FineClueComboEnum.FINE_CLUE.getCode());
                        if (Objects.nonNull(fineClueCompanyEntity) && fineClueCompanyEntity.getExtraExpiry() - fineClueCompanyEntity.getAddTime() <4 * RedisTimeConstant.LONG_DURATION){
                            i.setStatus(0);
                        }
                    }
                    if (Objects.equals(i.getAlias(), ValueAddedTypeEnum.CONTRACT_COMPARE.getAlias())){
                        Integer compareStatus = contractCompareUtil.getContractCompareStatus(enableApplicationListDTO.getCorpid());
                        // 合同比对过期或者试用，按钮展示为开通
                        if (Objects.equals(compareStatus, ContractCompareFeeStatusEnum.TRIAL.getType()) || Objects.equals(compareStatus, ContractCompareFeeStatusEnum.OVERDUE.getType())){
                            i.setStatus(0);
                        }else {
                            i.setStatus(1);
                        }
                    }
                }
            });
            // 电子面单，物流跟踪，价格管理，工商查询不是一个单独应用，从公司配置拿，塞一个假应用
            List<String> aliasList = Arrays.asList(CompanyConfigEnum.PRICE_MANAGE.getAlias(), CompanyConfigEnum.LOGISTICS_TRACKING.getAlias(), CompanyConfigEnum.ELECTRONIC_FACE_SHEET.getAlias(), CompanyConfigEnum.BUSINESS_SEARCH.getAlias(), CompanyConfigEnum.TPLUS.getAlias());
            Map<String, Object> param = new HashMap<>(2);
            param.put(ParameterConstant.CORPID, enableApplicationListDTO.getCorpid());
            param.put("configAliasIn", aliasList);
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            List<CompanyConfigEntity> companyConfigEntityList = companyConfigModel.findEntityList(param);
            if (CollectionsUtil.isNotEmpty(companyConfigEntityList)) {
                for (CompanyConfigEntity companyConfigEntity : companyConfigEntityList) {
                    PaasAppEntity paasAppEntity = new PaasAppEntity();
                    //新工商查询应用状态处理   旧公司工商查询已使用发脚本迁移，不做判断处理
                    if(Objects.equals(companyConfigEntity.getConfigAlias(),ValueAddedTypeEnum.BUSINESS_SEARCH.getAlias())){
                        FineClueCompanyEntity fineClueCompanyEntity = fineClueCompanyModel.getByCorpid(companyConfigEntity.getCorpid(), FineClueComboEnum.COMPANY_QUERY.getCode());
                        SearchCustomerCompanyEntity searchCustomerCompanyEntity = searchCustomerCompanyModel.getByCorpid(companyConfigEntity.getCorpid(), 2);
                        long currentTime = DateTimeUtil.getInt();
                        if (Objects.nonNull(fineClueCompanyEntity)){
                            //如果新公司工商查询是试用或者过期状态
                            if (fineClueCompanyEntity.getExtraExpiry() - fineClueCompanyEntity.getAddTime() <4 * RedisTimeConstant.LONG_DURATION || fineClueCompanyEntity.getExtraExpiry() < currentTime){
                                paasAppEntity.setStatus(0);
                            }else {
                                paasAppEntity.setStatus(1);
                            }
                        }
                    }
                    paasAppEntity.setId(companyConfigEntity.getId());
                    paasAppEntity.setCorpid(companyConfigEntity.getCorpid());
                    paasAppEntity.setEnable(Integer.valueOf(companyConfigEntity.getConfigValue()));
                    paasAppEntity.setAlias(companyConfigEntity.getConfigAlias());
                    paasAppEntity.setSaasMark(SaasMarkEnum.SAAS.getCode());
                    paasAppEntity.setName(companyConfigEntity.getConfigName());
                    paasAppEntity.setDel(companyConfigEntity.getDel());
                    paasAppEntity.setAddTime(companyConfigEntity.getAddTime());
                    paasAppEntity.setUpdateTime(companyConfigEntity.getUpdateTime());
                    list.add(paasAppEntity);
                }
            }
            enableApplicationListVO.setAppList(list);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e){
            LOG.error("paasApp数据库获取用户应用列表出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return enableApplicationListVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApplicationCopyVO copy(ApplicationCopyDTO applicationCopyDTO) throws XbbException {
        ApplicationCopyVO applicationCopyVO = new ApplicationCopyVO();
        try {
            Long appId = applicationCopyDTO.getAppId();
            String corpid = applicationCopyDTO.getCorpid();
            PaasAppEntity paas = paasAppModel.getByKey(appId, corpid);
            if (paas == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.APP_NOT_EXIST);
            }
            // 系统应用不允许复制
            if(SaasMarkEnum.SAAS.getCode().equals(paas.getSaasMark())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.NOT_ALLOW_COPY, paas.getName());
            }

            // 有字段删除的应用不准复制
            Map<String, Object> param = new HashMap<>();
            param.put("corpid", corpid);
            param.put("appId", appId);
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("recover", 0);
            Integer entitysCount = attrTrashModel.getEntitysCount(param);
            if (entitysCount > 0) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.NOT_ALLOW_COPY_BECAUSE_DELETE, paas.getName());
            }

            Integer count = validateAppLength(applicationCopyDTO.getCorpid());
            paas.setId(null);
            // 复制应用
            String name = paas.getName() + "_" + I18nMessageUtil.getMessage(CommonConstant.COPY);
            if(name.length() > NAME_LENGTH){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.APP_NAME_LENGTH_TOO_LONG);
            }
            if (Objects.equals(LocaleContextHolder.getLocale().getLanguage(), I18nStringConstant.ENGLISH_LANGUAGE)) {
                paas.setNameEn(name);
                String nameEn = paas.getNameEn() + "_" + I18nMessageUtil.getMessage(CommonConstant.COPY);
                paas.setName(nameEn);
            } else {
                paas.setName(name);
            }
            paas.setSort(count++);
            paasAppModel.insert(paas);
            String userId = applicationCopyDTO.getUserId();
            String userName = applicationCopyDTO.getLoginUserName();
            // 记录日志
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_APP), userName, paas.getName());
            String httpHeader = applicationCopyDTO.getHttpHeader();
            mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PAAS_APP, OperateTypeEnum.NEW, paas.getId().toString(), paas.getName(), memo, httpHeader);

            Long newAppId = paas.getId();
            applicationCopyVO.setAppId(newAppId);
            Map<String, Object> map = BeanUtil.convertBean2Map(applicationCopyDTO);
            List<PaasMenuEntityExt> menuList = paasMenuModel.getMenuList(map);
            if(menuList == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.MENU_NOT_EXIST);
            }

            OperateModuleTypeEnum operateModuleType = OperateModuleTypeEnum.PAAS_MENU;
            OperateTypeEnum operateType = OperateTypeEnum.NEW;
            for(PaasMenuEntityExt menuEntity : menuList) {
                PaasMenuEntityExt paasMenuEntityExt = new PaasMenuEntityExt();
                BeanUtil.copyProperties(menuEntity, paasMenuEntityExt);
                Long menuId = menuEntity.getId();
                paasMenuEntityExt.setId(null);
                paasMenuEntityExt.setAppId(newAppId);
                paasMenuModel.insert(paasMenuEntityExt);

                // 记录日志
                memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_MENU), userName, paas.getName(), paasMenuEntityExt.getName());
                mongoLogHelp.buildLog(corpid, userId, userName, operateModuleType, operateType, paasMenuEntityExt.getId().toString(), paasMenuEntityExt.getName(), memo, httpHeader);

                Long parentId = paasMenuEntityExt.getId();
                // 拷贝当前菜单节点下的所有表单和流程数据
                applicationCopyDTO.setMenuId(menuId);
                copyMenu(applicationCopyDTO, paasMenuEntityExt.getType(), parentId, newAppId, "");
                for (PaasMenuEntity paasMenuEntity: menuEntity.getSubMenuList()) {
                    menuId = paasMenuEntity.getId();
                    paasMenuEntity.setId(null);
                    paasMenuEntity.setAppId(newAppId);
                    paasMenuEntity.setParentId(parentId);

                    paasMenuModel.insert(paasMenuEntity);
                    // 记录日志
                    memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_MENU), userName, paas.getName(), paasMenuEntity.getName());
                    mongoLogHelp.buildLog(corpid, userId, userName, operateModuleType, operateType, paasMenuEntityExt.getId().toString(), paasMenuEntity.getName(), memo, httpHeader);

                    // 旧的菜单id
                    applicationCopyDTO.setMenuId(menuId);
                    copyMenu(applicationCopyDTO, paasMenuEntity.getType(), paasMenuEntity.getId(), newAppId, "");
                }
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("paasApp数据库复制应用出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return applicationCopyVO;
    }

    /**
     *
     * @param type 判断是否是流程表单和普通表单
     * @param newMenuId 新的菜单id
     * @param newAppId 新的应用id
     * @throws XbbException
     */
    @Override
    public void copyMenu(ApplicationCopyDTO applicationCopyDTO, Integer type, Long newMenuId, Long newAppId, String name) throws XbbException{
        try {
            String userId = applicationCopyDTO.getUserId();
            String corpid = applicationCopyDTO.getCorpid();
            String userName = applicationCopyDTO.getLoginUserName();
            if(type.equals(MenuTypeEnum.FORM.getType()) ||
                    type.equals(MenuTypeEnum.PROCESS_FORM.getType())) {
                Map<String, Object> param = BeanUtil.convertBean2Map(applicationCopyDTO, true);
                param.put("menuId", applicationCopyDTO.getMenuId());
                List<PaasFormEntityExt> formList = paasFormModel.list(param);
                if (formList != null && !formList.isEmpty()) {
                    PaasFormEntityExt paasFormEntityExt = formList.get(0);
                    Long formId = paasFormEntityExt.getId();
                    paasFormEntityExt.setId(null);
                    PaasFormEntity formEntity = new PaasFormEntity();
                    BeanUtil.copyProperties(paasFormEntityExt, formEntity);
                    formEntity.setAppId(newAppId);
                    formEntity.setMenuId(newMenuId);
                    if(StringUtil.isNotEmpty(name)){
                        formEntity.setName(name);
                    }
                    formEntity.setCreatorId(userId);
                    paasFormModel.insert(formEntity);

                    // 记录日志
                    String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_FORM), userName, formEntity.getName());
                    String httpHeader = applicationCopyDTO.getHttpHeader();
                    mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PAAS_FORM, OperateTypeEnum.NEW, formEntity.getId().toString(), formEntity.getName(), memo, httpHeader);

                    Long newFormId = formEntity.getId();
                    param.clear();
                    param = BeanUtil.convertBean2Map(applicationCopyDTO, true);
                    param.put("formId", formId);
                    PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
                    if (paasFormExplainEntity != null) {
                        paasFormExplainEntity.setId(null);
                        paasFormExplainEntity.setAppId(newAppId);
                        paasFormExplainEntity.setFormId(newFormId);
                        paasFormExplainEntity.setCreatorId(userId);
                        paasFormExplainEntity.setMenuId(newMenuId);
                        if (Objects.isNull(paasFormExplainEntity.getEnable())) {
                            paasFormExplainEntity.setEnable(1);
                        }
                        List<FieldAttrEntity> list = JSONObject.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
                        list.forEach(fieldAttrEntity->{
                            if (Objects.equals(BasicConstant.TWO, fieldAttrEntity.getIsOpen()) && Objects.equals(1, fieldAttrEntity.getIsRedundant())) {
                                // 将回收站的字段释放出来
                                fieldAttrEntity.setIsOpen(1);
                            }
                            if (ExplainUtil.isSubForm(fieldAttrEntity.getFieldType()) && Objects.nonNull(fieldAttrEntity.getSubForm())) {
                                fieldAttrEntity.getSubForm().getItems().forEach(item->{
                                    if (Objects.equals(BasicConstant.TWO, item.getIsOpen()) && Objects.equals(1, item.getIsRedundant())) {
                                        // 将回收站的字段释放出来
                                        item.setIsOpen(1);
                                    }
                                });
                            }
                        });
                        paasFormExplainEntity.setExplains(JSON.toJSONString(list));
                        paasFormExplainModel.insert(paasFormExplainEntity);

                        // 记录日志
                        memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_FORM_EXPLAIN), userName);
                        mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PAAS_FORM_EXPLAIN, OperateTypeEnum.NEW, paasFormExplainEntity.getId().toString(), "", memo, httpHeader);

                        if(Objects.equals(formEntity.getIsProcessForm(), 1) && !commonHelp.isOpenWorkFlow(corpid)){
                            param.clear();
                            param = BeanUtil.convertBean2Map(applicationCopyDTO, true);
                            param.put("formId", formId);
                            List<PaasProcessTemplateEntityExt> processTemplateList = paasProcessTemplateModel.list(param);
                            if (processTemplateList == null) {
                                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NOT_EXIST);
                            }
                            if (!processTemplateList.isEmpty()) {
                                PaasProcessTemplateEntityExt paasProcessTemplateEntityExt = processTemplateList.get(0);
                                PaasProcessTemplateEntity paasProcessTemplateEntity = new PaasProcessTemplateEntity();
                                BeanUtil.copyProperties(paasProcessTemplateEntityExt, paasProcessTemplateEntity);
                                paasProcessTemplateEntity.setId(null);
                                paasProcessTemplateEntity.setMenuId(newMenuId);
                                paasProcessTemplateEntity.setAppId(newAppId);
                                paasProcessTemplateEntity.setFormId(newFormId);
                                paasProcessTemplateEntity.setCreatorId(userId);
                                paasProcessTemplateModel.insert(paasProcessTemplateEntity);
                                Long newTemplateId = paasProcessTemplateEntity.getId();

                                // 记录日志
                                memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_PROCESS_TEMPLATE), userName, name);
                                mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PAAS_PROCESS_TEMPLATE,
                                        OperateTypeEnum.NEW, newTemplateId.toString(), name, memo, httpHeader);

                                param.clear();
                                param = BeanUtil.convertBean2Map(applicationCopyDTO, true);
                                param.put("formId", formId);
                                param.put("templateId", paasProcessTemplateEntityExt.getId()   );
                                List<PaasProcessTemplateNodeEntityExt> nodeList = paasProcessTemplateNodeModel.list(param);
                                if(nodeList == null) {
                                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.CONDITION_OPERATION_NOT_SPECIFIED);
                                }
                                List<PaasProcessTemplateNodeEntityExt> insertNodeList = new ArrayList<>();
                                for (PaasProcessTemplateNodeEntityExt templateNodeEntityExt: nodeList) {
                                    PaasProcessTemplateNodeEntityExt processTemplateNodeEntity = operateNode(templateNodeEntityExt, newAppId, newMenuId, newFormId, newTemplateId, applicationCopyDTO);
                                    insertNodeList.add(processTemplateNodeEntity);
                                }
                                if (!insertNodeList.isEmpty()) {
                                    paasProcessTemplateNodeModel.insertBatch(insertNodeList);
                                }
                            }
                        }
                    }else{
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
                    }
                } else {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
                }
            }
        } catch (XbbException e) {
            throw e;
        } catch(Exception e) {
            LOG.error("paasApp数据库复制菜单出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }


    @Override
    public AppEnableVO enableApp(AppEnableDTO appEnableDTO) throws XbbException {
        AppEnableVO appEnableVO = new AppEnableVO();
        Long id = appEnableDTO.getAppId();
        String corpid = appEnableDTO.getCorpid();
        PaasAppEntity paasAppEntity = paasAppModel.getByKey(id, corpid);
        if(Objects.isNull(paasAppEntity)){
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.APP_NOT_EXIST);
        }
        if(!SaasMarkEnum.PAAS.getCode().equals(paasAppEntity.getSaasMark())){
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.APP_NOT_ALLOW_ENABLE);
        }

        Integer enable = appEnableDTO.getEnable();
        String alias = paasAppEntity.getAlias();
        try {
            PaasAppEntity entity = new PaasAppEntity();
            entity.setId(id);
            entity.setCorpid(corpid);
            long now = DateUtil.getInt();
            entity.setUpdateTime(now);
            entity.setEnable(enable);
            paasAppModel.update(entity);
            //应用是市场管理 刷新缓存
            setEnable2RedisByAlias(corpid,alias,enable);
        } catch (Exception e) {
            LOG.error("paasApp.enableApp启用/关闭应用出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        String memo;
        OperateTypeEnum operateType;
        if (Objects.equals(BasicConstant.ONE, enable)) {
            memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_APP_ENABLE), appEnableDTO.getLoginUserName(), paasAppEntity.getName());
            operateType = OperateTypeEnum.ENABLE;
        } else {
            memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_APP_CLOSE), appEnableDTO.getLoginUserName(), paasAppEntity.getName());
            operateType = OperateTypeEnum.CLOSE;
        }
        // 记录日志
        mongoLogHelp.buildLog(corpid, appEnableDTO.getUserId(), appEnableDTO.getLoginUserName(), OperateModuleTypeEnum.PAAS_APP, operateType,
                paasAppEntity.getId().toString(), paasAppEntity.getName(), memo, appEnableDTO.getHttpHeader());

        return appEnableVO;
    }

    @Override
    public Boolean validateAppEnable(Long appId, String alias, Integer saasMark, String corpid) throws XbbException {
        return paasAppModel.validateAppEnable(appId, alias, saasMark, corpid);
    }

    @Override
    public CheckAllowRollBackVo checkAllowRollBack(CheckAllowRollBackDTO checkAllowRollBackDTO) throws XbbException {
        String corpid = checkAllowRollBackDTO.getCorpid();
        CheckAllowRollBackVo checkAllowRollBackVo = new CheckAllowRollBackVo();
        PaasAppEntity paasAppEntity = paasAppModel.getByKey(checkAllowRollBackDTO.getAppId(), corpid);
        MirrorRollBackDTO mirrorRollBackDTO = new MirrorRollBackDTO();
        BeanUtil.copyProperties(checkAllowRollBackDTO,mirrorRollBackDTO);
        mirrorRollBackDTO.setAlias(paasAppEntity.getAlias());
        mirrorRollBackDTO.setTargetCorpid(corpid);
        mirrorRollBackDTO.setAppInstallId(checkAllowRollBackDTO.getInstallId());
        Boolean flag = mirrorService.newCheckData(mirrorRollBackDTO);
        checkAllowRollBackVo.setFlag(!flag);

        //校验公司是否是试用期
        BasePackageInfoVO basePackageInfoFromRedis = packageService.getBasePackageInfoFromRedis(corpid);
        Integer vipNum = basePackageInfoFromRedis.getVipNum();
        if (Objects.equals(vipNum,BasicConstant.ZERO)){
            checkAllowRollBackVo.setIsProbation(true);
        }else{
            checkAllowRollBackVo.setIsProbation(false);
        }
        return checkAllowRollBackVo;
    }

    @Override
    public HasFormDataVO hasData(HasFormDataDTO hasFormDataDTO) throws XbbException {
        HasFormDataVO hasFormDataVO = new HasFormDataVO();
        try {
            Long appId = hasFormDataDTO.getAppId();
            String corpid = hasFormDataDTO.getCorpid();
            PaasAppEntity entity = paasAppModel.getByKey(appId, corpid);
            if (entity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.APP_NOT_EXIST);
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("appId", appId);
            param.put("formId", hasFormDataDTO.getFormId());
            param.put(StringConstant.CORPID, hasFormDataDTO.getCorpid());
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("start", 0);
            param.put("pageNum", 1);
            param.put(StringConstant.COLUMNS, "id");
            List<PaasFormDataEntityExt> dataList = paasFormDataModel.findEntitysWithoutSub(param);
            Integer count = dataList == null ? 1 : dataList.size();
            if (count == 0) {
                hasFormDataVO.setHasData(false);
            } else {
                // 有数据
                hasFormDataVO.setHasData(true);
            }
            param.clear();
            param.put(StringConstant.CORPID, hasFormDataDTO.getCorpid());
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("appId", hasFormDataDTO.getAppId());
            param.put("start", 0);
            param.put("pageNum", 1);
            List<PaasProcessDataEntity> processDataList = paasProcessDataModel.hasDataInApproval(param);
            count = processDataList == null ? 1 : processDataList.size();
            if (count > 0){
                // 有数据
                hasFormDataVO.setProcessHasData(true);
            } else {
                hasFormDataVO.setProcessHasData(false);
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("paasAppServiceImpl.hasData 报错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return hasFormDataVO;
    }

    /**
     * 缓存
     * @param coprid
     * @param alias 应用对应的别名
     * @param enable 应用的启用状态。 1启用，0关闭
     * @throws XbbException
     */
    @Override
    public void setEnable2RedisByAlias(String coprid, String alias, Integer enable) throws XbbException {
        proAppService.setEnable2RedisByAlias(coprid, alias, enable);

    }

    /**
     * 插入流程节点
     * @param sourceNode 指定数据
     * @param newAppId 新的应用id
     * @param newMenuId 新的菜单id
     * @param newFormId 新的表单id
     * @param newTemplateId 新的流程模板id
     * @return 流程节点id
     * @throws XbbException
     */
    private PaasProcessTemplateNodeEntityExt operateNode(PaasProcessTemplateNodeEntityExt sourceNode, Long newAppId, Long newMenuId, Long newFormId, Long newTemplateId, ApplicationCopyDTO applicationCopyDTO) throws XbbException{
        PaasProcessTemplateNodeEntityExt nodeEntity = new PaasProcessTemplateNodeEntityExt();
        try {

            BeanUtil.copyProperties(sourceNode, nodeEntity);
            nodeEntity.setId(null);
            nodeEntity.setAppId(newAppId);
            nodeEntity.setMenuId(newMenuId);
            nodeEntity.setFormId(newFormId);
            nodeEntity.setTemplateId(newTemplateId);
            nodeEntity.setCreatorId(applicationCopyDTO.getUserId());

        } catch (Exception e) {
            LOG.error("paasApp数据库复制应用出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return nodeEntity;
    }

    /**
     * 校验应用是否超过限制
     * @param corpid
     * @throws XbbException
     */
    private Integer validateAppLength(String corpid) throws XbbException {
        //套餐判断
        Integer status = packageStatusHelp.getPackageStatus(corpid, ValueAddedTypeEnum.CUSTOM_APPLICATION_NUM, 1);
        if(!Objects.equals(status, PackageStatusEnum.NORMAL.getCode()) && !Objects.equals(status, PackageStatusEnum.WARNING.getCode())){
            throw new XbbException(ProErrorCodeEnum.API_ERROR_260013);
        }
        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put("del", DelEnum.NORMAL.getDel());
        map.put("corpid", corpid);
        Integer count = paasAppModel.getEntitysCount(map);
        if(Objects.isNull(count)){
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return count;
    }
}
